//
//  Dictionary.Merge.swift
//  JLCommonKit
//
//  Created by Jiang Chencheng on 2024/8/16.
//

import Foundation

public extension Dictionary {
    enum MergingStrategy {
        case replaceExisting
        case keepExisting
    }
}

public extension Dictionary {
    mutating func merge(_ other: Dictionary, strategy: MergingStrategy = .replaceExisting) {
        switch strategy {
        case .replaceExisting:
            merge(other) { _, new in new }
        case .keepExisting:
            merge(other) { current, _ in current }
        }
    }

    func merging(_ other: Dictionary, strategy: MergingStrategy = .replaceExisting) -> Dictionary {
        switch strategy {
        case .replaceExisting:
            return merging(other) { _, new in new }
        case .keepExisting:
            return merging(other) { current, _ in current }
        }
    }

    mutating func merge(_ other: Dictionary?, strategy _: MergingStrategy = .replaceExisting) {
        guard let other = other else { return }
        merge(other)
    }

    func merging(_ other: Dictionary?, strategy _: MergingStrategy = .replaceExisting) -> Dictionary {
        guard let other = other else { return self }
        return merging(other)
    }
}

public extension Dictionary {
    static func +=(lhs: inout Dictionary, rhs: Dictionary) {
         lhs.merge(rhs)
    }
    
    static func +=(lhs: inout Dictionary, rhs: Dictionary?) {
        if let rhs = rhs { lhs.merge(rhs) }
    }
    
    static func +=(lhs: inout Dictionary?, rhs: Dictionary) {
        if var lhs = lhs { lhs.merge(rhs) } else { lhs = rhs }
    }

    static func +(lhs: Dictionary, rhs: Dictionary) -> Dictionary {
        lhs.merging(rhs)
    }
    
    static func +(lhs: Dictionary, rhs: Dictionary?) -> Dictionary {
        if let rhs = rhs { return lhs.merging(rhs) }
        return lhs
    }
    
    static func +(lhs: Dictionary?, rhs: Dictionary) -> Dictionary {
        if let lhs = lhs { return lhs.merging(rhs) }
        return rhs
    }
}
